package fr.efrei.musicpliz.dao.impl;

import java.util.List;

import javax.persistence.Query;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.mysql.jdbc.StringUtils;

import fr.efrei.musicpliz.dao.CompteDao;
import fr.efrei.musicpliz.dto.CompteDto;
import fr.efrei.musicpliz.entity.Artiste;
import fr.efrei.musicpliz.entity.ClientParticulier;
import fr.efrei.musicpliz.entity.ClientProfessionnel;
import fr.efrei.musicpliz.entity.Compte;
import fr.efrei.musicpliz.entity.Groupe;

/**
 * Implementation of CompteDao interface
 */
public class CompteDaoImpl extends AbstractDaoImpl<Compte> implements CompteDao {

	@Override
	@SuppressWarnings("unchecked")
	public <T extends Compte> List<T> getAllComptes(T instance) {
		Session session = (Session) entityManager.getDelegate();
		Criteria crit = session.createCriteria(instance.getClass());

		return crit.list();
	}

	@Override
	public Compte getCompteForEmail(String email) {
		Query query = entityManager
				.createQuery("from Compte where mail like :email");
		query.setParameter("email", email);

		return (Compte) query.getResultList().get(0);
	}
	
	@Override
	public Compte getCompteForId(int id) {
		Query query = entityManager
				.createQuery("from Compte where id =:id");
		query.setParameter("id", id);

		return (Compte) query.getResultList().get(0);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Compte> searchComptesForDto(CompteDto dto) {
		Session session = (Session) entityManager.getDelegate();

		// private CompteTypeEnum type;
		// private String nom;
		// private String adresse;
		// private int codePostal;
		// private String ville;
		// private String numero;
		// private String mail;
		// private String password;
		// private Date naissance;
		// private String prenom;
		// private String nomScene;
		// private String typeResto;
		// private String description;
		// private String instrument;
		// private String typeMusique;
		// private String material;
		Criteria crit = session.createCriteria(Compte.class);

		//TODO this copy paste Criteria-Adding should be solved a bit nicer..i guess
		if (dto.getType() != null) {
			switch (dto.getType()) {
			case ARTISTE:
				crit = session.createCriteria(Artiste.class);
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getPrenom()) ? crit : crit.add(Restrictions.like("prenom", dto.getPrenom()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getNomScene()) ? crit : crit.add(Restrictions.like("nomScene", dto.getNomScene()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getInstrument()) ? crit : crit.add(Restrictions.like("instrument", dto.getInstrument()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getTypeMusique()) ? crit : crit.add(Restrictions.like("typeMusique", dto.getTypeMusique()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getMaterial()) ? crit : crit.add(Restrictions.like("material", dto.getMaterial()));
				break;
			case GROUPE:
				crit = session.createCriteria(Groupe.class);
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getInstrument()) ? crit : crit.add(Restrictions.like("instrument", dto.getInstrument()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getTypeMusique()) ? crit : crit.add(Restrictions.like("typeMusique", dto.getTypeMusique()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getMaterial()) ? crit : crit.add(Restrictions.like("material", dto.getMaterial()));
				break;
			case CLIENT_PARTICULIER:
				crit = session.createCriteria(ClientParticulier.class);
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getPrenom()) ? crit : crit.add(Restrictions.like("prenom", dto.getPrenom()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getInstrument()) ? crit : crit.add(Restrictions.like("instrument", dto.getInstrument()));
				break;
			case CLIENT_PROFESSIONNEL:
				crit = session.createCriteria(ClientProfessionnel.class);
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getTypeResto()) ? crit : crit.add(Restrictions.like("typeResto", dto.getTypeResto()));
				crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getDescription()) ? crit : crit.add(Restrictions.like("description", dto.getDescription()));
				break;
			}
		}

		crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getNom()) ? crit : crit.add(Restrictions.like("nom", dto.getNom()));
		crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getAdresse()) ? crit : crit.add(Restrictions.like("adresse", dto.getAdresse()));
		crit = dto.getCodePostal() != 0 ? crit.add(Restrictions.eq("codePostal", dto.getCodePostal())) : crit;
		crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getVille()) ? crit : crit.add(Restrictions.like("ville", dto.getVille()));
		crit = StringUtils.isEmptyOrWhitespaceOnly(dto.getNumero()) ? crit : crit.add(Restrictions.like("numero", dto.getNumero()));
		crit = dto.getNaissance() != null ? crit.add(Restrictions.eq("naissance", dto.getNaissance())) : crit;
		crit = crit.addOrder(Order.asc("class"));
		crit = crit.addOrder(Order.asc("nom"));

		return crit.list();
	}
}
